#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include "TcpServer.h"

#define INTERNAL_CMD_MAX_NUM 10

int internal_tcp_creat_socket(void)
{
    int listen_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (listen_socket == -1)
    {
        perror("socket");
        return -1;
    }

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));

    addr.sin_family = AF_INET;
    addr.sin_port = htons(INTERNAL_TCP_PORT);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);

    int ret = bind(listen_socket, (struct sockaddr *)&addr, sizeof(addr));
    if (ret == -1)
    {
        perror("JKSdkTcp: bind");
        return -1;
    }

    ret = listen(listen_socket, INTERNAL_CMD_MAX_NUM);
    if (ret == -1)
    {
        perror("JKSdkTcp: listen");
        return -1;
    }

    return listen_socket;
}

int internal_tcp_wait_client(int listen_socket)
{
    struct sockaddr_in cliaddr;
    int addrlen = sizeof(cliaddr);

    /** 创建一个和客户端交流的套接字 **/
    int client_socket = accept(listen_socket, (struct sockaddr *)&cliaddr,(socklen_t *)&addrlen);
    if (client_socket == -1)
    {
        perror("accept");
        return -1;
    }

    return client_socket;
}

void internal_tcp_send_buff(int socket)
{
    send(socket, INTERNAL_TCP_HANDLE_OK,strlen(INTERNAL_TCP_HANDLE_OK), MSG_NOSIGNAL);
}

void internal_tcp_handle_client(int socket)
{
    char flag = 0;
    char test_buf[12] = {0};
    STcpInfo info;

    int ret;
    fd_set fd;
    // SJKComSecondTimer timer;
    struct timeval timeout;

    memset(&info, 0, sizeof(info));
    memset(&timeout, 0, sizeof(timeout));

    while (1)
    {
        FD_ZERO(&fd);
        FD_SET(socket,&fd);

        timeout.tv_sec = 5;
        timeout.tv_usec = 0;

        ret = select(socket + 1,&fd,(fd_set *)0, (fd_set *)0,&timeout);
        if(ret > 0)
        {
            int len = recv(socket, &info, INTERNAL_TCP_SIZE - 1, MSG_DONTWAIT);
            if (len > 0)
            {
                printf("recv %d,len: %d\n", len, info.len);
                printf("system-->%s\n", info.data);
                memcpy(test_buf, info.data, sizeof(test_buf));
                // system(info.data);
                internal_tcp_send_buff(socket);
                // break;
                flag = 1;
            }
        }
        else if(ret == 0)
        {
            #if 0
            if(Wrap_JKCom_second_timer(JKCOM_NOT_SET_TIME,&timer) >= 18)
            {
                JK_PRT_WARN(DEF_TAG,"tcp handle timeout\n");
                break;
            }
            #endif


        }
        else
        {
            printf("select error\n");
            break;
        }

        if (flag == 1)
        {
            printf("socket: %d,%s\n", socket, test_buf);
        }
        sleep(1);
    }

    close(socket);
}

union {
    int value;
    void* ptr;
} converter;

//结构体和联合体成员变量前缀统一加m
typedef struct
{
    unsigned int mOldTime;
    unsigned int mNewTime;
}StComTimeData,*pStComTimeData;

// 枚举成员前缀统一加E
typedef enum
{
    E_VOICES_LANGUAGE_CHINESE = 0,
    E_VOICES_LANGUAGE_ENGLISH,
    E_VOICES_LANGUAGE_JAPANESE,
    E_VOICES_LANGUAGE_KOREAN,
    E_VOICES_LANGUAGE_TAIWAN,
    E_VOICES_LANGUAGE_OTHER,
}EnComVoicesLanguage;

int main(void)
{
    EnComVoicesLanguage en;
    StComTimeData an;

    int listen_socket = internal_tcp_creat_socket();

    while (1)
    {
        pthread_t id;
        int client_socket;

        client_socket = internal_tcp_wait_client(listen_socket);
        converter.value = client_socket;
        pthread_create(&id, NULL, (void *)internal_tcp_handle_client,converter.ptr);
        pthread_detach(id);
        usleep(50 * 1000);
    }

    close(listen_socket);

    return 0;
}
